#! /usr/bin/env bash
set -e
cd "$(dirname "$0")/.."
version=$(cat .version)
verbose=$(echo "$@" | grep -q -- --verbose && echo true || echo false)
linux-cross-cc() {
  if ! which docker &> /dev/null
  then echo "[$triple] Unsupported: Docker not found" ; return 1
  elif uname | grep -q MINGW
  then echo "[$triple] Unsupported: Host is Windows" ; return 1
  fi
  echo "$@" | grep -q -- --supported && return 0
  (
    img=wlinkmeyer/$(uname -m)-cross
    [ "$verbose" = true ] && set -x
    docker run -v "$PWD:/src" --rm -w /src "$img" \
      "${toolchain_name}-g++" \
        --sysroot "/etc/sysroots/$triple" \
        -I "/usr/include/$toolchain_name" \
        -I "/etc/sysroots/$triple/usr/include" \
        -I "/etc/sysroots/$triple/usr/include/c++/12" \
        -I "/etc/sysroots/$triple/usr/include/$toolchain_name" \
        -I "/etc/sysroots/$triple/usr/include/$toolchain_name/c++/12" \
        -I watcher-c/include \
        -I include \
        -std=c++17 \
        -fno-exceptions \
        -fno-rtti \
        -fexpensive-optimizations \
        -fno-omit-frame-pointer \
        -fstrict-enums \
        -fstrict-overflow \
        -fstrict-aliasing \
        -fstack-protector-strong \
        -Os \
        $@
  )
}
macos-cc() {
  if ! uname | grep -q Darwin
  then echo "[$triple] Unsupported: Not on macOS" ; return 1
  fi
  echo "$@" | grep -q -- --supported && return 0
  (
    [ "$verbose" = true ] && set -x
    c++ \
      -target "$triple" \
      -I watcher-c/include \
      -I include \
      -std=c++17 \
      -fno-exceptions \
      -fno-rtti \
      -fno-omit-frame-pointer \
      -fstrict-enums \
      -fstrict-overflow \
      -fstrict-aliasing \
      -fstack-protector-strong \
      -Os \
      -framework CoreFoundation \
      -framework CoreServices \
      $@
    install_name_tool -add_rpath /usr/local/lib "$artifact"
  )
}
windows-cc() {
  if ! uname | grep -q MINGW
  then echo "[$triple] Unsupported: Not on Windows" ; return 1
  fi
  echo "$@" | grep -q -- --supported && return 0
  (
    [ "$verbose" = true ] && set -x
    clang++ \
      -target "$triple" \
      -I watcher-c/include \
      -I include \
      -std=c++17 \
      -fno-rtti \
      -fno-omit-frame-pointer \
      -fstrict-enums \
      -fstrict-overflow \
      -fstrict-aliasing \
      -fstack-protector-strong \
      -Os \
      $@
  )
}
build() {
  polycc() {
    if echo "$triple" | grep -q apple
    then macos-cc -o "$artifact" "${@:3}"
    elif echo "$triple" | grep -q windows
    then windows-cc -o "$artifact" "${@:3}"
    else linux-cross-cc -o "$artifact" "${@:3}"
    fi
  }
  triple=$1
  artifact=$2
  if echo "$@" | grep -q -- --supported
  then polycc --supported
  else
    if [ -e "$artifact" ]
    then echo "[$triple] Exists: $artifact"
    else
      [ -d "$(dirname "$artifact")" ] || mkdir -p "$(dirname "$artifact")"
      polycc -o "$artifact" "${@:3}"
      echo "$triple" | grep -q windows || sudo chown "$USER" "$artifact"
      echo -n "[$triple] Built: " ; file "$artifact"
    fi
  fi
}
polybuild() {
  triple=$1
  toolchain_name=$2
  case "$triple" in
    *-windows-*) so=dll ;;
    *) so=so ;;
  esac
  if build "$triple" --supported
  then
    if echo "$triple" | grep -q -- windows
    then build "$triple" "out/$triple/libwatcher-c.$so" -shared watcher-c/src/watcher-c.cpp
    else build "$triple" "out/$triple/libwatcher-c.$so" -shared -fPIC watcher-c/src/watcher-c.cpp
    fi
    build "$triple" "out/$triple/watcher" src/wtr/watcher/main.cpp -DWTR_WATCHER_VERSION_S=\""$(cat .version)"\"
    build "$triple" "out/$triple/tw" src/wtr/tiny_watcher/main.cpp
    [ -e "out/$triple/libwatcher-c.$so.$version" ] || cp "out/$triple/libwatcher-c.$so" "out/$triple/libwatcher-c.$so.$version"
    [ -f "out/$triple/watcher.hpp" ] || cp include/wtr/watcher.hpp "out/$triple/watcher.hpp"
    [ -f "out/$triple/watcher-c.h" ] || cp watcher-c/include/wtr/watcher-c.h "out/$triple/watcher-c.h"
    python3 tool/shasum.py "out/$triple" mk
    [ -e "out/$triple.tar" ] || (cd out && tar -cf "$triple.tar" "$triple")
    python3 tool/shasum.py "out/$triple.tar" mk
    [ -e "out/$triple.tar.gz" ] || gzip -c "out/$triple.tar" > "out/$triple.tar.gz"
    python3 tool/shasum.py "out/$triple.tar.gz" mk
  fi
}
echo "$@" | grep -q -- --help && {
  cat <<EOF
Usage: $0 [options]
Options:
  --clean                   Regenerate all build artifacts
  --list-targets            List all possible target triples
  --list-supported-targets  List the target triples supported for building from this host
  --target-<triple>         Build for a specific target (from --list-targets)
  --verbose                 Print some of the build commands
  --help                    Print this help message
EOF
  exit 0
}
while read -r triple toolchain_name
do
  if echo "$@" | grep -q -- --list-targets
  then echo "$triple"
  elif echo "$@" | grep -q -- --list-supported-targets
  then build "$triple" --supported &> /dev/null && echo "$triple"
  elif echo "$@" | grep -q -- --target && ! echo "$@" | grep -q -- "--target-$triple"
  then continue
  else
    echo "$@" | grep -q -- --clean && rm -rf "out/$triple"
    polybuild "$triple" "$toolchain_name"
  fi
done <<EOF
aarch64-apple-darwin nothing
aarch64-pc-windows-gnu nothing
aarch64-pc-windows-msvc nothing
aarch64-unknown-linux-gnu aarch64-linux-gnu
aarch64-unknown-linux-musl aarch64-linux-musl
armv7-unknown-linux-gnueabihf arm-linux-gnueabihf
armv7-unknown-linux-musleabihf arm-linux-musleabihf
x86_64-pc-windows-gnu nothing
x86_64-pc-windows-msvc nothing
x86_64-unknown-linux-gnu x86_64-linux-gnu
x86_64-unknown-linux-musl x86_64-linux-musl
EOF
